import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'package:string_validator/string_validator.dart';
import 'package:webview_flutter/webview_flutter.dart';

import '../../common/channel/action.dart';
import '../../common/config.dart';
import '../../common/utils/tracker.dart';
import '../../ui/dialog/exit.dart';

class WebScreen extends StatefulWidget {
  final String url;
  final bool closable;

  const WebScreen({super.key, required this.url, this.closable = true});

  @override
  State<WebScreen> createState() => _WebScreenState();
}

class _WebScreenState extends State<WebScreen> {
  final String title = Config.appName;

  late final WebViewController controller;

  final _WebIndex index = _WebIndex();

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider.value(
      value: index,
      builder: (context, child) {
        double progress = context.watch<_WebIndex>().value / 100.0;
        return Scaffold(
          backgroundColor: Colors.white,
          appBar: AppBar(
            // automaticallyImplyLeading: widget.closable,
            leading: GestureDetector(
              onTap: () {
                onClickPrevious(false);
              },
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: context.watch<_WebIndex>().canPop
                    ? const Icon(Icons.close, color: Colors.white)
                    : const Icon(Icons.arrow_back_ios, color: Colors.white),
              ),
            ),
            title: Text(title, style: const TextStyle(fontSize: 18)),
            backgroundColor: const Color(0xff4744d3),
          ),
          body: PopScope(
            canPop: false,
            onPopInvoked: onClickPrevious,
            child: Stack(
              children: [
                WebViewWidget(controller: controller),
                Visibility(
                  visible: progress < 1,
                  child: SizedBox(
                    height: 1,
                    child: LinearProgressIndicator(
                      backgroundColor: Colors.white,
                      valueColor:
                          const AlwaysStoppedAnimation(Color(0xff4744d3)),
                      value: progress,
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  @override
  void initState() {
    super.initState();
    // #docregion webview_controller
    controller = WebViewController()
      ..enableZoom(false)
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(
        NavigationDelegate(
          onProgress: (int progress) {
            // Update loading bar.
            index.go(progress);
          },
          onPageStarted: (String url) {},
          onPageFinished: (String url) async {
            index.pop(!await controller.canGoBack());
          },
          onWebResourceError: (WebResourceError error) {},
          onNavigationRequest: (NavigationRequest request) async {
            final String url = request.url;
            return await handleRequest(url);
          },
        ),
      );
    if (isURL(widget.url)) {
      controller.loadRequest(Uri.parse(widget.url));
    } else if (widget.url.startsWith('assets/')) {
      controller.loadFlutterAsset(widget.url);
    } else {
      controller.loadHtmlString(widget.url);
    }
  }

  Future<NavigationDecision> handleRequest(String url) async {
    final bool isHttpUrl = isURL(url);
    if (isHttpUrl) {
      return NavigationDecision.navigate;
    }
    LaunchResult result = await action.launch(url);
    switch (result) {
      case LaunchResult.complete:
        Tracker.trackJumpComplete();
        break;
      case LaunchResult.notFound:
        Tracker.trackJumpNotFound();
        break;
      case LaunchResult.error:
        Tracker.trackJumpError();
        break;
    }
    return NavigationDecision.prevent;
  }

  void onClickPrevious(bool didPop) async {
    if (await controller.canGoBack()) {
      await controller.goBack();
    } else {
      if (!context.mounted) return;
      showExitDialog(context, () {
        context.pop();
      });
      // context.pop();
    }
  }
}

class _WebIndex extends ChangeNotifier {
  int _value = 0;
  bool _canPop = true;

  int get value => _value;

  bool get canPop => _canPop;

  void go(int value) {
    _value = value;
    notifyListeners();
  }

  void pop(bool value) {
    _canPop = value;
    notifyListeners();
  }
}
